iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 20
2
Modern Web

美麗的邂逅-與安室....伊春系列 第 20

倒轉乾坤 (IOC)

  • 分享至 

  • xImage
  •  
這樣,在後的將要在前,在前的將要在後了。
  • IOC=Inverse of Control, DI=Dependency Injection
  • @Bean, @Component, @Service, @Repository, @Controller, @Value

Bean 符合特定規範的 Class,例如 Bean 可以被序列化。(不懂?簡單的說,就是產生的物件(instance,object)可以被轉成文字串,以文字串傳遞,又可以從文字串復活為物件(instance,object),這可以算是一種馴化,就是能被序列化的Bean,是"比較聽話的咖啡豆")
@Component 是特殊的 @Bean,而@Service,@Repository以及@Controller 是特殊的 @Component,“特殊的”以程式的說法就是 “繼承自”,即 @Component 繼承自 @Bean,或是說 @Bean 衍生 @Component。即

@Bean -> @Comonent -> (@Service, @Repository, @Controller)

IOC 是一種設計的概念。例如:我們要成立一個翻譯小組,有(張三,李四,王二麻子),這是固定的,在程式一開始設計就決定的,必須先有張三,李四,王二麻子,然後能成立翻譯小組;現在我們介紹另一個作法是,假設這個翻譯小組,其實是要懂俄文,懂英文,懂西班牙文的,因此這個翻譯小組變成 (懂俄文的人,懂英文的人,懂西班牙文的人),然後就算這個翻譯小組就成立了,另一方面,每個入會的人再去領牌子,例如:懂俄文、懂英文、懂西班牙文(至於相同內容的牌子是否只有一個,就是另外一個問題,因此也會衍生一些變化),然後,小組要出動時,再從牌子去選人,這樣是不是就倒過來了?先有了翻譯小組,人再入會。IOC另外有一個名稱就是 DI,就是要出動時,再 "注入" (injection) 實際的人,而不是一開始就決定的。接著我們比較一下,編程的差異:

0. 傳統的寫法 (new)

// 子類別(person)被父類別(group)用到,先定義

class person { … }

// 父類別(group)會用到子類別(person)

class group {
   person1 = new person(…);
   person2 = new person(…);
   person3 = new person(…);
   …
} 

1. Bean with derivatives & getBean

@Bean 放在函數(成員)之前(其實,前後無關,他們是不同的檔案,也可以稱作平行,就是彼此無關),例如:

@Bean(name= {"desc","Parameter_Type"})
@Scope(value = "prototype")
public static Description getInstance(String name) {
	return new Description(name);
}

呼叫的方式,必須先取得 context, 這有點講究,

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Description.class); 
Description desc = (Description) context.getBean("desc","mattrew");
((AnnotationConfigApplicationContext) context).close();

第一行 AnnotationConfigApplicationConext() 也可以改成三行

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(Description.class);
context.reflash();

重新創建,當然可以,但 ApplicationContext 系統會自動創建,創建後不會關閉,因此也可以直接當作類別的 data member 來使用,例如:

@Autowired
private ApplicationContext context;

還有一點必須要注意,在class Description 中必須包含有一個沒有參數的 Constructor. (可以用Source > Generate Constructors from Superclass 自動編程)。

2. Component & Autowired

透過司普令符(Spring Boot)更簡化,@Component 放在 Class 宣告之前(符要貼對位置),如:

@Component
public class Description {
	private String name;
	private String descripion;
    …

在使用時,可以用 @Autowired 或是 @Resource,@Autowired 預設是類型名稱(type),而@Resource 預設是以名稱(Name)來尋找 @Component

    @Autowired
    @Value("mattrew")
    private Description desc;

或是我們用名稱來處理, 其中 @Value 提供一個參數的 Constructor 使用。

@Component(“desc”)
public class Description {
	private String name;
	private String descripion;
    …

使用端編程如下:

    @Resource(name=”desc”)
    private Description desc;

比較使用端,在@Autowired 時 @Value 是有作用的,但是在@Resouce中就沒有作用。
class Description 範例 (使用 @Component)

@Component("desc")
public class Description {
	public Description() {
		super();
	}
	public Description(String name) {
		super();
		this.setName(name);
	}

	private void reflashDescription() {
		switch (name.toLowerCase()) {
		case "mattrew":
			this.descripion = "Chapter 1, New Testment.";
			break;
		case "mark":
			this.descripion = "Chapter 2, New Testment.";
			break;
		case "luke":
			this.descripion = "Chapter 3, New Testment";
			break;
		case "john":
			this.descripion = "Chapter 4, New Testment";
			break;
		default:
			this.descripion = "Other than 4 Gospels.";
		}
	}

	private String name;
	private String descripion;
	public String getDescripion() {
		return descripion;
	}	
	public String getName() {
		return name;
	}	
	public void setName(String name) {
		this.name = name;
		this.reflashDescription();
	}
}

https://ithelp.ithome.com.tw/upload/images/20191005/20120951Iba8JZR57C.png


上一篇
從中央到地方 (Controller to JSP)
下一篇
過路劫財 (AOC)
系列文
美麗的邂逅-與安室....伊春30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言